package cn.yeziji.forum.dao.impl;

import cn.yeziji.forum.common.key.WebsocketCacheKey;
import cn.yeziji.forum.common.websocket.Chatroom;
import cn.yeziji.forum.converter.ChatroomConverter;
import cn.yeziji.forum.dao.base.ForumChatroomBaseDao;
import cn.yeziji.forum.dao.intf.ForumChatroomDao;
import cn.yeziji.forum.dao.iquery.ChatroomQuery;
import cn.yeziji.forum.dao.iupdater.ChatroomUpdater;
import cn.yeziji.forum.entity.ForumChatroomEntity;
import cn.yeziji.forum.entity.ForumUserEntity;
import cn.yeziji.forum.mapper.ForumChatroomMapper;
import cn.yeziji.forum.mapper.ForumUserMapper;
import cn.yeziji.forum.utils.CacheUtils;
import cn.yeziji.forum.utils.JwtOperaUtils;
import cn.yeziji.forum.utils.ListsCollect;
import cn.yeziji.forum.vo.chatroom.UserMsgStatisticVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 论坛聊天记录逻辑实现层
 *
 * @author gzkemays
 * @since 2022/03/27 18:41
 */
@Repository
@Slf4j
public class ForumChatroomDaoImpl extends ForumChatroomBaseDao implements ForumChatroomDao {
  @Resource ForumChatroomMapper chatroomMapper;
  @Resource ForumUserMapper userMapper;
  @Resource CacheUtils cache;
  @Resource HttpServletRequest request;

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void batchSave(Collection<ForumChatroomEntity> set) {
    // 获取更新的数据
    List<ForumChatroomEntity> updates =
        set.stream().filter(chat -> Objects.nonNull(chat.getId())).collect(Collectors.toList());
    ListsCollect.of(updates).notEmptyConsumer(this::updateEntityByIds);
    // 获取插入的数据
    List<ForumChatroomEntity> inserts =
        set.stream().filter(chat -> Objects.isNull(chat.getId())).collect(Collectors.toList());
    ListsCollect.of(inserts).notEmptyConsumer((list) -> chatroomMapper.insertBatch(list));
  }

  @Override
  public List<ForumChatroomEntity> getChatroomRecords(String chatroom, boolean openCache) {
    Set<ForumChatroomEntity> set = new LinkedHashSet<>();
    if (openCache) {
      List<Object> recordsCache =
          ListsCollect.of(cache.getBlurHashKey(WebsocketCacheKey.PRIVATE_TO_AND_FROM, chatroom))
              .orElseEmpty();
      for (Object obj : recordsCache) {
        if (obj instanceof Chatroom) {
          Chatroom cr = (Chatroom) obj;
          set.add(ChatroomConverter.INSTANCE.wbMsgConvertToEntity(cr));
        }
      }
    }
    // 获取数据库中的聊天记录
    set.addAll(chatroomMapper.listEntity(ChatroomQuery.getRecordsByChatroomName(chatroom)));
    return set.stream()
        .sorted(Comparator.comparing(ForumChatroomEntity::getCreateTime))
        .collect(Collectors.toList());
  }

  @Override
  public void updateChatroomNameByNickname(String nickname) {
    Integer userId = JwtOperaUtils.getUserIdByRequest(request);
    ForumUserEntity userEntity = userMapper.findById(userId);
    String target = userEntity.getNickname();

    List<ForumChatroomEntity> entities =
        chatroomMapper.listEntity(ChatroomQuery.getChatroomByNickname(target));
    entities.forEach(
        entity -> {
          Chatroom chatRoom = ChatroomConverter.INSTANCE.entityConvertToChatroom(entity);
          if (entity.getFrom().equals(target)) {
            chatRoom.setFrom(nickname);
          }
          if (entity.getTo().equals(target)) {
            chatRoom.setTo(nickname);
          }
          chatRoom.reBuildChatroomName();
          entity.setChatroom(chatRoom.getChatroom());
          super.updateBy(ChatroomUpdater.updateChatroomNameById(entity));
        });
  }

  @Override
  public List<UserMsgStatisticVO> getUserMsgByUserId(Integer userId) {
    return statistic(userId);
  }

  @Override
  public List<UserMsgStatisticVO> getUserStatistic() {
    Integer userId = JwtOperaUtils.getUserIdByRequest(request);
    return statistic(userId);
  }

  private List<UserMsgStatisticVO> statistic(Integer userId) {
    String nickname = userMapper.findById(userId).getNickname();
    // 查找数据库中的存储数据
    List<ForumChatroomEntity> entities =
        mapper().listEntity(ChatroomQuery.getUserStatisticQuery(nickname));
    // 查找缓存中的聊天数据
    List<Object> blurHashKey =
        cache.getBlurHashKey(WebsocketCacheKey.PRIVATE_TO_AND_FROM, nickname);
    for (Object obj : blurHashKey) {
      if (obj instanceof Chatroom) {
        Chatroom chatroom = (Chatroom) obj;
        if (chatroom.getTo() != null && chatroom.getTo().equals(nickname)) {
          entities.add(ChatroomConverter.INSTANCE.wbMsgConvertToEntity((Chatroom) obj));
        }
      }
    }

    if (!CollectionUtils.isEmpty(entities)) {
      List<ForumChatroomEntity> collect =
          entities.stream()
              .sorted(
                  (e1, e2) -> {
                    String from1 = e1.getFrom();
                    String from2 = e2.getFrom();
                    if (from1.compareTo(from2) == 0) {
                      return e1.getCreateTime().compareTo(e2.getCreateTime());
                    }
                    return from1.compareTo(from2);
                  })
              .collect(Collectors.toList());
      // 获取每个用户最后一个数据
      Set<String> tempFromUsers =
          collect.stream()
              .map(ForumChatroomEntity::getFrom)
              .collect(Collectors.toCollection(LinkedHashSet::new));
      List<UserMsgStatisticVO> statisticVos = new ArrayList<>();
      // 列表索引
      int index = -1;
      for (String fromUserName : tempFromUsers) {
        int count = 0;
        for (ForumChatroomEntity entity : collect) {
          String from = entity.getFrom();
          if (from.equals(fromUserName)) {
            count++;
            // 值相同时对列表索引进行累加
            index++;
          }
        }
        ForumChatroomEntity entity = collect.get(index);
        statisticVos.add(UserMsgStatisticVO.buildByChatroomEntity(entity, count));
      }
      return statisticVos;
    }
    return Collections.emptyList();
  }
}
